package ml.practicum.feature;

import java.io.Serializable;
import java.util.List;
/**
 * Feature class describes a feature describing information in a data set in a and it's
 * role and settings for classification. This class encapsulates the information needed
 * to process the feature input of type <V> to processed format. 
 * This processing information includes:
 * <ul>
 * 	<li> The feature label </li>
 * 	<li> Whether the feature represents an input or an output</li>
 * 	<li> The feature input format: numerical or nominal</li>
 *  <li> The desired output type: numerical or nominal</li>
 *  <li> The maximum and minimal value in the data set the feature describes 
 * (for numerical values)</li>
 *	<li> The number of discrete steps to process to for numerical values being 
 * discretisized 
 *  </li>  
 * </ul>
 * 
 * <p> A feature role can be <code> FeatureRole.INPUT , FeatureRole.OUTPUT,
 * FeatureRole.IGNORE</code>. Ignore in this case is an indicator for later
 * processing to do nothing with this feature Features with the role of <code>
 * IGNORE</code> Can contain information in all the other field but it should  
 * never be used.</p> 
 * <p>The mapping of possible string values is a list, in this mapping the ordering
 * is important changing the order of the strings in the list changes the mapping.
 * Since they are mapped to their index. 
 * </p>
 * 
 * @author jfs230
 * @version %I% %G%
 * @param <V>	the Class type to process the information to, this value should be 
 * <code>Serializable</code> because Features contain settings and information that
 * needs to be able to be stored and read.
 */
public interface Feature<V extends Serializable> extends Serializable { 
	/**
	 * Describes a numerical or nominal data type.
	 * The constant <code>DISCRETE</code> is chosen for Nominal values because both
	 * nominal and numerical start with an n. This way the 2 are more distinguishable 
	 * @author jfs230
	 *
	 */
	enum FeatureDataType {
		DISCRETE, NUMERICAL
	}
	
	/**
	 * Describes the role an feature for processing the data set. <code>INPUT</code> for 
	 * classification <code>OUTPUT</code> as class description or <code>IGNORE</code> to 
	 * do nothing with the feature values.
	 *  
	 * @author Joscha
	 *
	 */
	enum FeatureRole {
		INPUT,OUTPUT,IGNORE
	}
	
	/**
	 * Sets the label of the feature so it can be mapped to a feature header of data
	 * @param label		the label of the feature as described in a header
	 */
	void setLabel(String label);
	
	/**
	 * Gets the label of the feature so it can be mapped to a feature header of data
	 * @return the label of the feature as described in a header
	 */
	String getLabel();
	
	/**
	 * Sets the role of a feature for processing. 
	 * 
	 * @see FeatureRole
	 * @param inputOutputOrIgnore 	the processing role to assign to the feature
	 */
	void setRole(FeatureRole inputOutputOrIgnore);
	
	/**
	 * Gets the role of a feature for processing
	 * @see FeatureRole
	 * @return the description of the part the feature plays for processing
	 */
	FeatureRole getRole();
	
	/**
	 * Sets the expected maximum value of a feature. If the formal maximum in a data set
	 * is infinite <code>max</code> can still be set to a lower value to establish a 
	 * range of normally expected values
	 * <p>this forms a range of expected values together with <code>setMin</code></p>
	 * @param max
	 * @see setMin;
	 */
	void setMax(int max);
	
	/**
	 * Gets normally expected maximum the actual maximum is always assumed to be infinite
	 * @see setMax
	 * @see getMin
	 * @return the expected maximum (maximum within normal range)
	 */
	int getMax();

	/**
	 * Sets the expected minimum value of a feature. If the formal minimum in a data set
	 * is infinite <code>min</code> can still be set to a lower value to establish a 
	 * range of normally expected values
	 * <p>this forms a range of expected values together with <code>setMax</code></p>
	 * @param max
	 * @see setMin;
	 */
	void setMin(int min);
	
	/**
	 * Gets normally expected minimum the actual minimum is always assumed to be infinite
	 * @see setMin
	 * @see getMax
	 * @return the expected maximum (maximum within normal range)
	 */
	int getMin();	
	
	/**
	 * Sets the amount of discrete steps numerical values will be divided in when processed
	 * to discrete values.
	 * @param steps		the amount of discrete steps chosen
	 * @see getDiscreteSteps
	 * @see getProcessTo()
	 */
	void setDiscreteSteps(int steps);
	
	/**
	 * Gets the amount of discrete steps numerical values will be divided in when processed
	 * to discrete values.
	 * @returns the amount of discrete steps chosen
	 * @see setDiscreteSteps
	 * @see getProcessTo()
	 */
	int getDiscreteSteps();
	
	/**
	 * Sets the feature input format: numerical or nominal.
	 * @param discreteOrNumerical 		the input format
	 * @see FeatureDataType
	 */
	void setInputType(FeatureDataType discreteOrNumerical);
	
	/**
	 * Gets the feature input format: numerical or nominal.
	 * @return the input format
	 * @see FeatureDataType
	 */	
	FeatureDataType getInputType();
	
	/**
	 * Sets the feature output format: numerical or nominal.
	 * The value format to process to.
	 * @param discreteOrNumerical 		the output format
	 * @see FeatureDataType
	 */
	void setProcessTo(FeatureDataType discreteOrNumerical );
	
	/**
	 * Gets the feature output format: numerical or nominal.
	 * The value format to process to.
	 * @return the output format
	 * @see FeatureDataType
	 */	
	FeatureDataType getProcessTo();
	
	/**
	 * Sets a mapping of string the possible values (for nominal features) 
	 * <p>The mapping of possible string values is a list, in this mapping the ordering
	 * is important changing the order of the strings in the list changes the mapping.
	 * Since they are mapped to their index. 
	 * </p>
	 * 
	 * @param discreteValues the list of possible string values
	 */
	void setMapping(List<V> discreteValues);
	
	/**
	 * Gets a mapping of string the possible values (for nominal features) 
	 * <p>The mapping of possible string values is a list, in this mapping the ordering
	 * is important changing the order of the strings in the list changes the mapping.
	 * Since they are mapped to their index. 
	 * </p>
	 * 
	 * @return discreteValues the list of possible string values
	 */
	List<V> getMapping();
}
